package com.example.lock;

import io.etcd.jetcd.ByteSequence;
import io.etcd.jetcd.Client;
import lombok.Data;

import java.nio.charset.StandardCharsets;


/***
 * EtcdLock实现了Lock接口，用于实现基于Etcd的分布式锁
 */
@Data
public class EtcdLock implements Lock {

    private String lockKey;

    private ByteSequence lockByteSequence;

    private int ttl;

    private Client client;

    private io.etcd.jetcd.Lock lock;

    private LockListener listener;

    public EtcdLock(Client client, String lockKey, int ttl, LockListener listener) {
        this.client = client;
        this.lockKey = lockKey;
        this.ttl = ttl;
        this.listener = listener;
        this.lockByteSequence = ByteSequence.from(lockKey, StandardCharsets.UTF_8);
    }

    /***
     * 获取分布式锁，如果获取成功，就执行listener.onLock()方法，否则执行listener.onUnlock()方法
     * @throws Exception
     */
    @Override
    public void lock() throws Exception {
        this.lock = this.client.getLockClient();
        long grantId = this.client.getLeaseClient().grant(this.ttl).get().getID();
        lock.lock(this.lockByteSequence, grantId).whenComplete((lockResponse, throwable) -> {
            if (lockResponse != null) {
                listener.onLock();
            } else {
                listener.onUnlock();
            }
        }).get();
    }

    /***
     * 释放分布式锁
     */
    @Override
    public void unlock() {
        this.listener.releaseLock();
        this.lock.unlock(lockByteSequence);
    }
}
